import axios from 'axios';
import { message } from 'antd';
import { gateway } from '@/config/env'
import { clearLogin, getAccessToken, getRefreshToken, setAccessToken } from './storage';
import { refreshToken } from '@/views/login/api';

axios.defaults.timeout = 5000;
//跨域请求，允许保存cookie
axios.defaults.withCredentials = true;

// 请求拦截器
axios.interceptors.request.use(
  config => {
    // 跨域配置
    config.headers['Accept'] = 'application/json';
    config.headers['Content-Type'] = 'application/json;charset=utf8';
    config.headers['Access-Control-Allow-Origin'] = '*';
    // 校验token是否有效，如果离过期时间少于5分钟则刷新token
    const authorization = getAccessToken();
    if (authorization) {
      config.headers['Authorization'] = `Bearer ${authorization}`
    }
    if (!config.url.startsWith(gateway)) {
      config.url = gateway + config.url;
    }
    return config;
  },
  error => {
    message.error('请求失败！' + error);
    return Promise.reject(error);
  }
);

// token刷新方案，主动刷新+被动刷新，主动：定时任务，一个小时刷新一次；被动：接口返回401，然后刷新token
// 响应拦截器
let isRefreshing = false;
let requests = [];

// 刷新 token 方法
const refreshTokenAndRetry = (error) => {
  const config = error.config;
  return new Promise((resolve, reject) => {
    const refreshTokenValue = getRefreshToken();
    if (!refreshTokenValue) {
      message.warning('登录过期，请重新登录！');
      window.location.href = '/login';
      clearLogin();
      reject(new Error('登录过期，请重新登录'));
      return;
    }

    refreshToken(refreshTokenValue).then(resp => {
      const data = resp.data;
      setAccessToken(data);
      config.headers['Authorization'] = `Bearer ${data}`;
      resolve(axios(config));
    }).catch(() => {
      message.warning('登录过期，请重新登录！');
      window.location.href = '/login';
      clearLogin();
      reject(new Error('登录过期，请重新登录'));
    }).finally(() => {
      isRefreshing = false;
      requests.forEach(cb => cb());
      requests = [];
    });
  });
};

// 挂起请求
const suspendRequest = (error) => {
  return new Promise(resolve => {
    requests.push(() => {
      const config = error.config;
      config.headers['Authorization'] = `Bearer ${getAccessToken()}`;
      resolve(axios(config));
    });
  });
};

// 响应拦截器
axios.interceptors.response.use(
  response => {
    // 响应成功返回数据
    return response.data;
  },
  error => {
    const response = error.response;

    if (response.status === 401) {
      if (!isRefreshing) {
        isRefreshing = true;
        return refreshTokenAndRetry(error);
      } else {
        return suspendRequest(error);
      }
    } else if (response.status === 404) {
      message.error('接口不存在！');
      return Promise.reject(new Error('接口不存在'));
    } else {
      let msg = response.data?.msg;
      if (!msg) {
        msg = '系统异常，请稍后再试！';
      }
      message.error(msg);
      return Promise.reject(new Error(msg));
    }
  }
);

export default axios;